package com.ddm.service.impl.webImpl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ddm.dto.webDTO.UserUpdateDTO;
import com.ddm.dto.webDTO.WebResetPasswordDTO;
import com.ddm.entity.webEntity.Plan;
import com.ddm.service.impl.vxImpl.UserServiceImpl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ddm.constant.MessageConstant;
import com.ddm.dto.webDTO.WebLoginDTO;
import com.ddm.dto.webDTO.WebRegisterDTO;
import com.ddm.entity.vxEntity.User;
import com.ddm.exception.DataErrorException;
import com.ddm.mapper.UserMapper;
import com.ddm.mapper.VerificationCodeMapper;
import com.ddm.result.Result;
import com.ddm.service.vxService.UserService;
import com.ddm.service.webService.PlanService;
import com.ddm.service.webService.WebUserService;
import com.ddm.utils.BeanCopyUtil;
import com.ddm.utils.RedisUtil;
import com.ddm.utils.SendMUtil;
import com.ddm.utils.WebJwtUtil;
import com.ddm.vo.webVo.WebUserVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author horizon
 * @since 2025-01-17
 */
@Service
@Slf4j
public class WebUserServiceImpl extends ServiceImpl<UserMapper, User> implements WebUserService {
    @Autowired
    private SendMUtil sendMUtil;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserService userService;
    @Autowired
    private PlanService planService;
    @Autowired
    private VerificationCodeMapper verificationCodeMapper;
    @Autowired
    private UserServiceImpl userServiceImpl;
    @Autowired
    private RedisUtil redisUtil;

//    @Autowired
//    private WebJwtUtil jwtUtil;
    @Autowired
    private WebJwtUtil jwtUtil1;

//    @Autowired
//    private SmsService smsService;

//    @Autowired
//    private JavaMailSender javaMailSender;

//    @Value("${spring.mail.username}")
//    private String fromEmail;

    @Override
    @Transactional
    public void register(WebRegisterDTO registerDTO) {

        // 1. 验证码校验
        if (registerDTO.getVerificationCode() == null || registerDTO.getVerificationCode().trim().isEmpty()) {
//            throw new RuntimeException("验证码不能为空");
           throw new DataErrorException(MessageConstant.VERIFY_CODE_ERROR);
        }
        Result<Boolean> verifyResult = sendMUtil.verifyCode(registerDTO.getPhoneNum(),registerDTO.getVerificationCode());
        if (!verifyResult.isSuccess()) {
//            throw new RuntimeException(verifyResult.getMsg());
            throw new DataErrorException(MessageConstant.VERIFY_OVER_TIME);
        }



        // 检查用户名是否已存在
        User existingUser = userMapper.findByUsername(registerDTO.getUserName());
        if (existingUser != null) {
//            throw new RuntimeException("用户名已存在");
            throw new DataErrorException(MessageConstant.USERNAME_EXIST);
        }

//        // 检查邮箱是否已存在
//        existingUser = userMapper.findByEmail(registerDTO.getEmail());
//        if (existingUser != null) {
//            throw new DataErrorException(MessageConstant.EMAIL_EXIST);
//        }

        // 检查手机号是否已存在
        existingUser = userMapper.findByPhoneNum(registerDTO.getPhoneNum());
        if (existingUser != null) {
            throw new DataErrorException(MessageConstant.PHONE_EXIST);
        }

        // 创建新用户（明文存储密码，实际项目中应加密）
//获得openId
//        String openid = userServiceImpl.getOpenId(registerDTO.getPassword());
        User user = BeanCopyUtil.BeanCopy(registerDTO, User.class);
        user.setUserType(0); // 默认普通用户
//        user.setOpenid(openid);
        userMapper.insert(user);

        // 删除验证码
//        redisUtil.del(key);
    }
    //用户名登录
    @Override
    public WebUserVO login(WebLoginDTO loginDTO) {
        // 验证验证码
//        String key = getRedisKey(loginDTO.getVerifyType(), loginDTO.getUsageType(), loginDTO.getUserName());
//        String code = (String) redisUtil.get(key);
//
//        if (code == null || !code.equals(loginDTO.getVerificationCode())) {
//            throw new RuntimeException("验证码错误或已过期");
//        }

        // 根据登录ID查找用户
        User user = null;
        if (loginDTO.getUserName().contains("@")) {
            user = userMapper.findByEmail(loginDTO.getUserName());
        } else if (loginDTO.getUserName().matches("^1[3-9]\\d{9}$")) {
            user = userMapper.findByPhoneNum(loginDTO.getUserName());
        } else {
            user = userMapper.findByUsername(loginDTO.getUserName());
        }

        if (user == null) {
//            throw new RuntimeException("用户不存在");

            throw new DataErrorException(MessageConstant.ACCOUNT_NOT_FOUND);

        }

        // 验证密码（明文比较，实际项目中应加密比较）
        if (!loginDTO.getPassword().equals(user.getPassword())) {
            throw new RuntimeException("密码错误");
        }

        // 生成JWT
        Map<String, Object> claims = new HashMap<>();
        claims.put("userId", user.getId());
        claims.put("username", user.getUserName());
        claims.put("userType", user.getUserType());
        String token = jwtUtil1.generateToken(claims);


        // 构建返回对象
        WebUserVO userVO = new WebUserVO();
        BeanUtils.copyProperties(user, userVO);
        userVO.setToken(token);

        // 删除验证码
//        redisUtil.del(key);

        return userVO;
    }
//手机号验证码登录
    @Override
    public WebUserVO login2(WebLoginDTO loginDTO) {
        // 1. 验证码校验
        if (loginDTO.getVerificationCode() == null || loginDTO.getVerificationCode().trim().isEmpty()) {
            throw new RuntimeException("验证码不能为空");
        }
        Result<Boolean> verifyResult = sendMUtil.verifyCode(loginDTO.getPhoneNum(), loginDTO.getVerificationCode());
        if (!verifyResult.isSuccess()) {
            throw new DataErrorException(MessageConstant.VERIFY_OVER_TIME);
        }

        // 2. 根据手机号或邮箱查找用户
        User user = null;
//    if (loginDTO.getUserName().contains("@")) {
//        // 包含@符号，尝试按邮箱查询
//        user = userMapper.findByEmail(loginDTO.getUserName());
//    } else
   if (loginDTO.getPhoneNum().matches("^1[3-9]\\d{9}$")) {
        //符合手机号格式，尝试按手机号查询
        user = userMapper.findByPhoneNum(loginDTO.getPhoneNum());
    }

    if (user == null) {
        throw new DataErrorException(MessageConstant.ACCOUNT_NOT_FOUND);
    }

//    // 3. 验证密码（明文比较，实际应加密，如 BCrypt）
//    if (!loginDTO.getPassword().equals(user.getPassword())) {
//        throw new RuntimeException("密码错误");
//    }

    // 4. 生成JWT
    Map<String, Object> claims = new HashMap<>();
    claims.put("userId", user.getId());
    claims.put("username", user.getUserName());
    claims.put("userType", user.getUserType());
    String token = jwtUtil1.generateToken(claims);

    // 5. 构建返回对象
    WebUserVO userVO = new WebUserVO();
    BeanUtils.copyProperties(user, userVO);
    userVO.setToken(token);

    return userVO;
}

    @Override
    public User getUserInfoById(long userId) {
        // 调用联表查询方法
        return userMapper.selectUserById(userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateUserInfo( UserUpdateDTO userDTO) {
        // 1. 转换DTO为实体（仅更新需要的字段）
        User user = new User();
        user.setId(userDTO.getId());
        try {
            // 2. 仅当 DTO 字段有值时才设置（避免将 null 传入Mapper）
            if (userDTO.getUserName() != null) {
                user.setUserName(userDTO.getUserName());
            }
            if (userDTO.getEmail() != null) {
                user.setEmail(userDTO.getEmail());
            }
            if (userDTO.getPlanId() != null) {
                String planId=userDTO.getPlanId();
                Plan plan = planService.getById(planId);
                if (plan == null) {
                    log.error("套餐不存在，planId: {}", planId);
                    throw new IllegalArgumentException("套餐不存在，planId: " + planId);
                }
                String targetUserType = getTargetUserTypeByPlanId(planId);
                // 4. 设置用户升级类型
                user.setUserType(Integer.valueOf(targetUserType));
                log.info("用户升级类型：planId={}, 升级后用户类型={}", planId, targetUserType);
            }
            if (userDTO.getPhoneNum() != null) {
                user.setPhoneNum(userDTO.getPhoneNum().trim());
            }
            // 3. 执行更新，通过影响行数判断是否成功
            int affectedRows = userMapper.updateUser(user);
            // 通过查询验证更新结果
            User updatedUser = userMapper.selectUserById(user.getId());
            log.info("查询验证更新结果 ", updatedUser);
            return  updatedUser != null;
        } catch (Exception e) {
            log.error("更新用户信息失败", e);
            return false;
        }
    }

    /**
     * 辅助方法：根据 PlanId 映射对应的用户类型
     * @param planId 套餐ID（Long类型，与Plan表id一致）
     * @return 对应的用户类型（0普通用户，1管理员，2是99元个人会员版，3是199专业会员版，4是299高级会员版（即VIP））
     */
    private String getTargetUserTypeByPlanId(String planId) {
        // 按业务规则定义 PlanId 与用户类型的映射
        return switch (planId) {
            case "4" -> "2";         // PlanId=4 → 个人会员
            case "5" -> "3";         // PlanId=5 → 专业会员
            case "6" -> "3";         // PlanId=6 → 高级会员VIP
            case "7" -> "0";         // PlanId=7 → 免费用户
            default -> "0";          // 未匹配的 PlanId → 默认类型（如普通用户）
        };
    }

    @Override
    @Transactional
    public Result<String> resetPasswordByVerificationCode(WebResetPasswordDTO resetPasswordDTO) {
        // 1. 验证码校验
        if (resetPasswordDTO.getVerificationCode() == null || resetPasswordDTO.getVerificationCode().trim().isEmpty()) {
            throw new DataErrorException(MessageConstant.VERIFY_CODE_NONUll);
        }

        // 验证验证码是否正确
        Result<Boolean> verifyResult = sendMUtil.verifyCode(resetPasswordDTO.getPhoneNum(), resetPasswordDTO.getVerificationCode());
        if (!verifyResult.isSuccess()) {
//            throw new RuntimeException(verifyResult.getMsg());
            throw new DataErrorException(MessageConstant.VERIFY_OVER_TIME);
        }

        // 2. 检查手机号是否存在
        User existingUser = userMapper.findByPhoneNum(resetPasswordDTO.getPhoneNum());
        if (existingUser == null) {
            throw new DataErrorException(MessageConstant.PHONE_NOT_EXIST);
        }

//        // 3. 检查新密码是否符合要求（这里可以根据实际需求添加密码强度验证）
//        if (resetPasswordDTO.getNewPassword() == null || resetPasswordDTO.getNewPassword().length() < 6) {
//            throw new DataErrorException(MessageConstant.PASSWORD_FORMAT_ERROR);
//        }

        // 4. 检查两次输入的密码是否一致
        if (!resetPasswordDTO.getNewPassword().equals(resetPasswordDTO.getConfirmPassword())) {
            throw new DataErrorException(MessageConstant.PASSWORD_NOT_MATCH);
        }

//        // 5. 重置密码（实际项目中应加密存储密码）
//        // 这里假设你有一个处理密码加密的方法
//        String encryptedPassword = encryptPassword(resetPasswordDTO.getNewPassword());
//        existingUser.setPassword(encryptedPassword);

//         6. 更新用户密码
        userMapper.updatePassword(existingUser.getId(), existingUser.getPassword(), resetPasswordDTO.getNewPassword());

            return Result.success("密码更新成功");

        // 7. 删除已使用的验证码
        // redisUtil.del(verificationCodeKey);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateAvatar(long userId, String photoUrl) {
        try {
            // 1. 查询用户原始信息（记录旧头像，用于后续对比）
            User originalUser = userMapper.selectUserById(userId);
            if (originalUser == null) {
                log.error("用户不存在，userId: {}", userId);
                return false;
            }
            String oldPhotoUrl = originalUser.getPhotoUrl(); // 保存旧头像URL
            // 2. 执行更新（不管返回行数，只要不抛异常就认为SQL执行成功）
            User updateUser = new User();
            updateUser.setId(userId); // 仅携带更新必要的字段（避免冗余字段影响）
            updateUser.setPhotoUrl(photoUrl);
            userMapper.updateUser(updateUser); // 建议新增“按ID更新头像”的专用Mapper方法
            // 3. 事务内强制刷新数据（关键：避免快照读，获取最新数据）
            // 用“悲观锁”查询（InnoDB引擎有效，强制读最新数据）
            User updatedUser = userMapper.selectUserByIdForUpdate(userId);
            // 4. 业务逻辑验证：更新后头像是否与目标URL一致
            if (updatedUser != null && photoUrl.equals(updatedUser.getPhotoUrl())) {
                log.info("头像更新成功，userId: {}, 旧URL: {}, 新URL: {}", userId, oldPhotoUrl, photoUrl);
                return true;
            }
            // 5. 极端情况：SQL执行成功但数据未更新（触发事务回滚）
            log.warn("头像更新异常：SQL执行成功但数据未同步，userId: {}", userId);
            throw new RuntimeException("头像更新后数据未同步"); // 抛异常触发事务回滚
        } catch (RuntimeException e) {
            log.error("头像更新业务异常，userId: {}", userId, e);
            return false; // 事务已回滚，返回失败
        } catch (Exception e) {
            log.error("头像更新系统异常，userId: {}", userId, e);
            return false; // 其他异常（如SQL错误），返回失败
        }
    }


    @Override
    public Integer getUserTypeById(Long userId) {
        return userMapper.selectUserTypeById(userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result updatePassword2(Integer userId, String oldPassword, String newPassword) {
        try {
            // 检查旧密码是否正确
          User user = userMapper.selectUserById((long)userId);
            if (user == null ) {
                log.error("用户不存在，userId: {}", userId);
                return Result.error("用户不存在");
            }

            if (!oldPassword.equals(user.getPassword())) {
                log.error("旧密码验证失败，userId: {}", userId);
                log.error("旧密码是，oldPassword: {}",user.getPassword());
                return Result.error("旧密码验证失败");
            }

            if (oldPassword.equals(newPassword)) {
                log.error("新旧密码一致，userId: {}", userId);
                return Result.error("新旧密码一致");
            }

            // 更新密码
            userMapper.updatePassword(userId, oldPassword,newPassword);

            // 验证更新结果
            User updatedUser = userMapper.selectUserById((long)userId);
            if (updatedUser == null || !newPassword.equals(updatedUser.getPassword())) {
                String errorMsg = "密码更新后验证失败，userId: " + userId;
                log.error(errorMsg);
                return Result.error(errorMsg);
            }

            return Result.success("密码更新成功");
        } catch (Exception e) {
            log.error("更新密码失败，userId: {}", userId, e);
            return Result.error("密码更新失败");
        }
    }

    public List<User> getAllUsersWithDeleted() {
        return baseMapper.selectAllWithDeleted();
    }

    // 分页带筛选条件的查询（包括已删除）
    public IPage<User> getAllUsersWithConditionPage(Integer pageNum, Integer pageSize,
                                                    String userName, Integer deleted) {
        Page<User> page = new Page<>(pageNum, pageSize);
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.ne("user_type", 1); // 默认只查普通用户
        // 用户名模糊查询
        if (userName != null && !userName.isEmpty()) {
            queryWrapper.like("user_name", userName);
        }

        // 按删除状态筛选
        if (deleted != null) {
            queryWrapper.eq("deleted", deleted);
        }

        return baseMapper.selectAllWithCondition(page, queryWrapper);
    }
//
//    public void sendVerificationCode(String target, Integer type, Integer usageType) {
//        // 生成6位验证码
//        String code = String.format("%06d", new Random().nextInt(999999));
//
//        // 保存到Redis，有效期5分钟
//        String key = getRedisKey(type, usageType, target);
//        redisUtil.set(key, code, 300);
//
//        // 保存记录到数据库
//        VerificationCode verificationCode = new VerificationCode();
//        verificationCode.setTarget(target);
//        verificationCode.setCode(code);
//        verificationCode.setType(type);
//        verificationCode.setUsageType(usageType);
//        verificationCode.setExpireTime(LocalDateTime.now().plusMinutes(5));
//        verificationCodeMapper.insert(verificationCode);
//
//        // 调用短信/邮件服务发送验证码
//        try {
//            if (type == 1) {
//                smsService.sendSms(target, code);
//            } else {
//                sendEmail(target, code);
//            }
//        } catch (Exception e) {
//            // 记录错误日志并删除Redis中的验证码
//            log.error("发送验证码失败: {}", e.getMessage());
//            redisUtil.del(key);
//            throw new RuntimeException("验证码发送失败，请稍后再试");
//        }
//    }

//    @Override
//    public User validateToken(String token) {
//        if (token == null || !token.startsWith("Bearer ")) {
//            return null;
//        }
//
//        token = token.substring(7);
//
//        try {
//            if (!jwtUtil.validateToken(token)) {
//                return null;
//            }
//
//            String username = jwtUtil.extractUsername(token);
//            return userMapper.findByUsername(username);
//        } catch (Exception e) {
//            return null;
//        }
//    }

//    private String getRedisKey(Integer type, Integer usageType, String target) {
//        String prefix = type == 1 ? "SMS_CODE:" : "EMAIL_CODE:";
//        String usage = usageType == 1 ? "REGISTER:" : "LOGIN:";
//        return prefix + usage + target;
//    }

//    private void sendEmail(String to, String code) {
//        SimpleMailMessage message = new SimpleMailMessage();
//        message.setFrom(fromEmail);
//        message.setTo(to);
//        message.setSubject("验证码 - 账户安全验证");
//        message.setText("您的验证码是：" + code + "，有效期5分钟。如非本人操作，请忽略此邮件。");
//        javaMailSender.send(message);
//        log.info("邮件验证码已发送至: {}", to);
//    }
}